home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright 1991, 1992, 1993, 1994, Silicon Graphics, Inc.
- * All Rights Reserved.
- *
- * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
- * the contents of this file may not be disclosed to third parties, copied or
- * duplicated in any form, in whole or in part, without the prior written
- * permission of Silicon Graphics, Inc.
- *
- * RESTRICTED RIGHTS LEGEND:
- * Use, duplication or disclosure by the Government is subject to restrictions
- * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
- * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
- * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
- * rights reserved under the Copyright Laws of the United States.
- */
-
- #include "parse.h"
- #include <math.h>
- #include "generic.h"
-
- #define DIM 5
- #define TINY 1e-20
-
- extern float fxmin, fxmax, fymin, fymax;
-
- long ludecompose(double a[DIM][DIM], long indx[DIM])
- {
- register i, j, k;
- long imax;
- register float sum;
- float dum, big;
- register double vv[DIM];
-
- for (i = 0; i < DIM; i++) {
- big = 0.0;
- for (j = 0; j < DIM; j++)
- if (fabs(a[i][j]) > big)
- big = fabs(a[i][j]);
- if (big == 0.0) {
- return 0;
- }
- vv[i] = 1.0/big;
- }
- for (j = 0; j < DIM; j++) {
- if (j > 0) {
- for (i = 0; i < j; i++) {
- sum = a[i][j];
- if (i > 0) {
- for (k = 0; k < i; k++)
- sum -= a[i][k]*a[k][j];
- a[i][j] = sum;
- }
- }
- }
- big = 0.0;
- for (i = j; i < DIM; i++) {
- sum = a[i][j];
- if (j > 0) {
- for (k = 0; k < j; k++)
- sum -= a[i][k]*a[k][j];
- a[i][j] = sum;
- }
- dum = vv[i]*fabs(sum);
- if (dum > big) {
- big = dum;
- imax = i;
- }
- }
- if (j != imax) {
- for (k = 0; k < DIM; k++) {
- dum = a[imax][k];
- a[imax][k] = a[j][k];
- a[j][k] = dum;
- }
- vv[imax] = vv[j];
- }
- indx[j] = imax;
- if (j != DIM - 1) {
- if (a[j][j] == 0.0)
- a[j][j] = TINY;
- dum = 1.0/a[j][j];
- for (i = j+1; i < DIM; i++)
- a[i][j] = a[i][j]*dum;
- }
- }
- if (a[DIM-1][DIM-1] == 0.0)
- a[DIM-1][DIM-1] = TINY;
- return 1;
- }
-
- void lubksb(double a[DIM][DIM], long indx[DIM], double b[DIM])
- {
- long i, j;
- long ip, ii;
- register double sum;
-
- ii = -1;
- for (i = 0; i < DIM; i++) {
- ip = indx[i];
- sum = b[ip];
- b[ip] = b[i];
- if (ii != -1) {
- for (j = ii; j < i; j++)
- sum -= a[i][j]*b[j];
- } else if (sum != 0.0)
- ii = i;
- b[i] = sum;
- }
- for (i = DIM-1; i >= 0; i--) {
- sum = b[i];
- if (i < DIM-1) {
- for (j = i+1; j < DIM; j++)
- sum = sum - a[i][j]*b[j];
- }
- b[i] = sum/a[i][i];
- }
- }
-
- void linetangenttoconic(line *l)
- {
- conic *c = (conic *)l->c.p1;
- vertex *v = (vertex *)l->c.p2;
- if (v->w == 0.0) {
- l->v1.xw = l->v2.xw = 1000.0;
- l->v1.yw = -1.0; l->v2.yw = 1.0;
- l->v1.w = l->v2.w = 0.0;
- homogenizeline(l);
- return;
- }
- if ((v->c.type == VERTONCONIC && (v->c.p1 == c)) ||
- (v->c.type == VERTLINECONIC1 && (v->c.p2 == c)) ||
- (v->c.type == VERTLINECONIC2 && (v->c.p2 == c))) {
- double x = v->xw, y = v->yw;
- // v had better be on the conic
- l->v1.xw = x; l->v1.yw = y; l->v1.w = 1.0; l->v2.w = 1.0;
- float dx = (c->bb*x+2.0*c->cc*y+c->ee);
- float dy = - (c->bb*y+2.0*c->aa*x+c->dd);
- float den = fabs(dx) + fabs(dy);
- l->v2.xw = x + dx/den;
- l->v2.yw = y + dy/den;
- homogenizeline(l);
- } else {
- l->v1.w = l->v2.w = 1.0;
- float alpha = c->aa*v->xw + c->bb*v->yw/2.0 + c->dd/2.0;
- float beta = c->bb*v->xw/2.0 + c->cc*v->yw + c->ee/2.0;
- float gamma = c->dd*v->xw/2.0 + c->ee*v->yw/2.0 + c->ff;
- float A = c->aa*beta*beta - c->bb*alpha*beta + c->cc*alpha*alpha;
- float B = 2*c->cc*alpha*gamma - c->bb*beta*gamma + c->dd*beta*beta - c->ee*alpha*beta;
- float C = c->cc*gamma*gamma - c->ee*gamma*beta + c->ff*beta*beta;
- float Disc = (B*B - 4*A*C);
- if (Disc < 0) {
- l->v1.xw = l->v2.xw = 1000.0;
- l->v1.yw = -1.0; l->v2.yw = 1.0;
- l->v1.w = l->v2.w = 0.0;
- homogenizeline(l);
- return;
- }
- Disc = sqrt(Disc);
- if (l->c.type == LINETANGENTCONIC1)
- l->v1.xw = (-B + Disc)/(2.0*A);
- else
- l->v1.xw = (-B - Disc)/(2.0*A);
- l->v1.yw = (-gamma - alpha*l->v1.xw)/beta;
- l->v2.xw = v->xw; l->v2.yw = v->yw;
- homogenizeline(l);
- }
- }
-
- void conic_vvvvv(conic *c)
- {
- double x[5], y[5], b[5];
- double a[5][5];
- long indx[5];
-
- vertex *v1 = (vertex *)c->c.p1;
- vertex *v2 = (vertex *)c->c.p2;
- vertex *v3 = (vertex *)c->c.p3;
- vertex *v4 = (vertex *)c->c.p4;
- vertex *v5 = (vertex *)c->c.p5;
- x[0] = v1->xw; y[0] = v1->yw;
- x[1] = v2->xw; y[1] = v2->yw;
- x[2] = v3->xw; y[2] = v3->yw;
- x[3] = v4->xw; y[3] = v4->yw;
- x[4] = v5->xw; y[4] = v5->yw;
-
- for (long i = 0; i < 5; i++) {
- a[i][0] = x[i]*x[i];
- a[i][1] = x[i]*y[i];
- a[i][2] = y[i]*y[i];
- a[i][3] = x[i];
- a[i][4] = y[i];
- }
- b[0] = b[1] = b[2] = b[3] = b[4] = -1.0;
-
- if (0 == ludecompose(a, indx)) {
- c->aa = c->bb = c->cc = c->dd = c->ee = c->ff = 0.0;
- return;
- }
- lubksb(a, indx, b);
-
- c->aa = b[0];
- c->bb = b[1];
- c->cc = b[2];
- c->dd = b[3];
- c->ee = b[4];
- c->ff = 1.0;
- }
-
- void conic_lllll(conic *c)
- {
- double x[5], y[5], w[5], b[5];
- double a[5][5];
- long indx[5];
-
- line *l1 = (line *)c->c.p1;
- line *l2 = (line *)c->c.p2;
- line *l3 = (line *)c->c.p3;
- line *l4 = (line *)c->c.p4;
- line *l5 = (line *)c->c.p5;
- x[0] = l1->XW; y[0] = l1->YW; w[0] = l1->W;
- x[1] = l2->XW; y[1] = l2->YW; w[1] = l2->W;
- x[2] = l3->XW; y[2] = l3->YW; w[2] = l3->W;
- x[3] = l4->XW; y[3] = l4->YW; w[3] = l4->W;
- x[4] = l5->XW; y[4] = l5->YW; w[4] = l5->W;
-
- for (long i = 0; i < 5; i++) {
- a[i][0] = x[i]*x[i];
- a[i][1] = x[i]*y[i];
- a[i][2] = y[i]*y[i];
- a[i][3] = x[i]*w[i];
- a[i][4] = y[i]*w[i];
- b[i] = -w[i]*w[i];
- }
- //b[0] = b[1] = b[2] = b[3] = b[4] = -1.0;
-
- if (0 == ludecompose(a, indx)) {
- c->aa = c->bb = c->cc = c->dd = c->ee = c->ff = 0.0;
- return;
- }
- lubksb(a, indx, b);
- //float det = b[0]*b[2] + b[1]*b[3]*b[4]/4 - b[2]*b[3]*b[3]/4
- // - b[0]*b[4]*b[4]/4 - b[1]*b[1];
- c->aa = (b[2] - b[4]*b[4]/4);
- c->bb = (b[3]*b[4]/2 - b[1]);
- c->cc = (b[0] - b[3]*b[3]/4);
- c->dd = (b[1]*b[4]/2 - b[2]*b[3]);
- c->ee = (b[1]*b[3]/2 - b[0]*b[4]);
- c->ff = (b[0]*b[2] - b[1]*b[1]/4);
- //c->aa = b[0];
- //c->bb = b[1];
- //c->cc = b[2];
- //c->dd = b[3];
- //c->ee = b[4];
- //c->ff = 1.0;
- }
-
- void projecttoconic(vertex *v, conic *con)
- {
- float x = v->xw, y = v->yw;
- float dist = 1.0e30, dt;
- float xval, yval, xbest, ybest, u;
-
- for (xval = fxmin; xval <= fxmax; xval += .01) {
- float a = con->cc;
- float b = con->bb*xval + con->ee;
- float c = con->aa*xval*xval + con->dd*xval + con->ff;
- if ((u = b*b - 4.0*a*c) >= 0) {
- float disc = sqrt(b*b - 4.0*a*c);
- float y1 = (-b + disc)/(2*a);
- float y2 = (-b - disc)/(2*a);
- if ((dt=(x-xval)*(x-xval)+(y1-y)*(y1-y))<dist) {
- dist = dt;
- xbest = xval;
- ybest = y1;
- }
- if ((dt=(x-xval)*(x-xval)+(y2-y)*(y2-y))<dist) {
- dist = dt;
- xbest = xval;
- ybest = y2;
- }
- }
- }
- for (yval = fymin; yval <= fymax; yval += .01) {
- float a = con->aa;
- float b = con->bb*yval + con->dd;
- float c = con->cc*yval*yval + con->ee*yval + con->ff;
- if ((u = b*b - 4.0*a*c) >= 0) {
- float disc = sqrt(b*b - 4.0*a*c);
- float x1 = (-b + disc)/(2*a);
- float x2 = (-b - disc)/(2*a);
- if ((dt=(x-x1)*(x-x1)+(y-yval)*(y-yval))<dist) {
- dist = dt;
- xbest = x1;
- ybest = yval;
- }
- if ((dt=(x-x2)*(x-x2)+(y-yval)*(y-yval))<dist) {
- dist = dt;
- xbest = x2;
- ybest = yval;
- }
- }
- }
- for (xval = xbest - .01; xval <= xbest + .01; xval += .0003) {
- float a = con->cc;
- float b = con->bb*xval + con->ee;
- float c = con->aa*xval*xval + con->dd*xval + con->ff;
- if ((u = b*b - 4.0*a*c) >= 0) {
- float disc = sqrt(b*b - 4.0*a*c);
- float y1 = (-b + disc)/(2*a);
- float y2 = (-b - disc)/(2*a);
- if ((dt=(x-xval)*(x-xval)+(y1-y)*(y1-y))<dist) {
- dist = dt;
- xbest = xval;
- ybest = y1;
- }
- if ((dt=(x-xval)*(x-xval)+(y2-y)*(y2-y))<dist) {
- dist = dt;
- xbest = xval;
- ybest = y2;
- }
- }
- }
- for (yval = ybest - .01; yval <= ybest+.01; yval += .0003) {
- float a = con->aa;
- float b = con->bb*yval + con->dd;
- float c = con->cc*yval*yval + con->ee*yval + con->ff;
- if ((u = b*b - 4.0*a*c) >= 0) {
- float disc = sqrt(b*b - 4.0*a*c);
- float x1 = (-b + disc)/(2*a);
- float x2 = (-b - disc)/(2*a);
- if ((dt=(x-x1)*(x-x1)+(y-yval)*(y-yval))<dist) {
- dist = dt;
- xbest = x1;
- ybest = yval;
- }
- if ((dt=(x-x2)*(x-x2)+(y-yval)*(y-yval))<dist) {
- dist = dt;
- xbest = x2;
- ybest = yval;
- }
- }
- }
- if (dist < 10000000.0) {
- v->xw = xbest; v->yw = ybest; v->w = 1.0;
- } else v->w = 0.0;
- }
-
-